import utils from '../core/utils';
import logger from '../core/logger';
import { BUNDLE_NAME } from '../core/dict';
import deviceManager from '@ohos.distributedHardware.deviceManager';

export default class remoteDeviceManage {
  private subscribeId: number = 100;
  private callback: () => void = null;
  private authCallback: () => void = null;
  public deviceList: Array<deviceManager.DeviceInfo> = [];
  public discoverList: Array<deviceManager.DeviceInfo> = [];
  private deviceManager: deviceManager.DeviceManager = undefined;

  registerDeviceListCallback(callback) {
    if (typeof (this.deviceManager) !== 'undefined') {
      this.registerDeviceListCallbackImplement(callback);
      return;
    }
    try {
      deviceManager.createDeviceManager(BUNDLE_NAME, (error, value) => {
        if (error) {
          logger.error(error);
          return;
        }
        this.deviceManager = value;
        this.registerDeviceListCallbackImplement(callback);
      });
    } catch (error) {
      logger.error(error)
    }
  }

  changeStateOnline(device) {
    try {
      this.deviceList[this.deviceList.length] = device;
      this.callback();
      if (utils.isEmpty(this.authCallback)) {
        this.authCallback();
        this.authCallback = null;
      }
    } catch (e) {
      logger.error(e);
    }
  }

  changeState(device, state) {
    try {
      if (this.deviceList.length <= 0) {
        this.callback();
        return;
      }
      if (state === deviceManager.DeviceStateChangeAction.READY) {
        let list = new Array()
        for (let i = 0; i < this.deviceList.length; i++) {
          if (this.deviceList[i].deviceId !== device.deviceId)
            list[i] = device;
        }
        this.deviceList = list;
        this.callback();
      } else {
        for (let j = 0; j < this.deviceList.length; j++) {
          if (this.deviceList[j].deviceId === device.deviceId) {
            this.deviceList[j] = device;
            break;
          }
        }
        this.callback();
      }
    } catch (e) {
      logger.error(e);
    }
  }

  registerDeviceListCallbackImplement(callback) {
    try {
      this.callback = callback;
      if (this.deviceManager === undefined) {
        this.callback();
        return;
      }
      let list = this.deviceManager.getTrustedDeviceListSync();
      if (typeof (list) !== 'undefined' && typeof (list.length) !== 'undefined')
        this.deviceList = list;
    } catch (error) {
      logger.error(error);
    }
    this.callback();
    try {
      this.deviceManager.on('deviceStateChange', (data) => {
        if (utils.isEmpty(data))
          return;
        switch (data.action) {
          case deviceManager.DeviceStateChangeAction.ONLINE:
            this.changeStateOnline(data.device);
            break;
          case deviceManager.DeviceStateChangeAction.READY:
            this.changeState(data.device, deviceManager.DeviceStateChangeAction.READY);
            break;
          case deviceManager.DeviceStateChangeAction.CHANGE:
            this.changeState(data.device, deviceManager.DeviceStateChangeAction.CHANGE);
            break;
        }
      });
      this.deviceManager.on('deviceFound', (data) => {
        if (utils.isEmpty(data))
          return;
        this.deviceFound(data);
      });
    } catch (error) {
      logger.error(error);
    }
    this.startDeviceDiscovery();
  }

  deviceFound(data) {
    try {
      for (let i = 0;i < this.discoverList.length; i++) {
        if (this.discoverList[i].deviceId === data.device.deviceId)
          return;
      }
      this.discoverList[this.discoverList.length] = data.device;
      this.callback();
    } catch (error) {
      logger.error(error);
    }
  }

  startDeviceDiscovery() {
    try {
      this.subscribeId = Math.floor(65536 * Math.random())
      let info = {
        subscribeId: this.subscribeId,
        mode: 0xAA,
        medium: 2,
        freq: 2,
        isSameAccount: false,
        isWakeRemote: true,
        capability: 0
      }
      this.deviceManager.startDeviceDiscovery(info);
    } catch (error) {
      logger.error(error);
    }
  }

  unregisterDeviceListCallback() {
    try {
      this.deviceManager.stopDeviceDiscovery(this.subscribeId);
    } catch (error) {
      logger.error(error);
    }
    try {
      this.deviceManager.off('deviceStateChange');
      this.deviceManager.off('deviceFound');
      this.deviceManager.off('discoverFail');
      this.deviceManager.off('serviceDie');
    } catch (error) {
      logger.error(error);
    }
    this.deviceList = [];
    this.discoverList = [];
  }

  authenticateDevice(device, callBack) {
    for (let i = 0; i < this.discoverList.length; i++) {
      try {
        if (this.discoverList[i].deviceId !== device.deviceId)
          continue;
        let authParam = {
          'authType': 1,
          'appIcon': '',
          'appThumbnail': '',
          'extraInfo': {
            'targetPkgName': BUNDLE_NAME,
            'appName': 'bilibili_manga',
            'appDescription': 'bilibili_manga',
            'business': '0'
          }
        }
        this.deviceManager.authenticateDevice(device, authParam, (err) => {
          if (err) {
            logger.error(err);
            this.authCallback = null;
            return;
          }
          this.authCallback = callBack;
        })
      } catch (error) {
        logger.error(error);
      }
    }
  }
}